/*
Autor: Alexander Savochkin, 2010
New BSD License
*/

#define BOOST_TEST_MODULE SRCLFTest
#include <boost/test/unit_test.hpp>

#include <string>
#include <boost/optional.hpp>
#include <boost/variant.hpp>

using std::string;
using boost::optional;
using boost::get;

#include "CommandASTActions.h"
#include "CommandParser.h"

using namespace SRCLF;
using namespace SRCLF::ClientRequestParsing;
using namespace SRCLF::ClientRequestParsing::AST;

const double Tolerance = 1e-8;

bool checkParsed(Command& cmd)
{
	if(!cmd.command)
		return false;
	return true;
}

bool matchChannelName(const string& channel_name,const Command& cmd)
{
	const ChannelCommand &chnnel_cmd = get<ChannelCommand>(cmd.command.get());
	if(chnnel_cmd.channel_name != channel_name)
		return false;
	return true;
}

bool matchChannelInputGet(const Command& cmd)
{
	const ChannelCommand &channel_cmd = get<ChannelCommand>(cmd.command.get());
	const ChannelInputCommand *input_cmd_ptr = get<ChannelInputCommand>(&(channel_cmd.channel_command));
	if (!input_cmd_ptr)
		return false;
	const InputGetCommand* get_cmd_ptr = get<InputGetCommand>(&(input_cmd_ptr->input_command));
	if (!get_cmd_ptr)
		return false;
	return true;
}

bool matchChannelOutputSet(double value, const Command& cmd)
{
	const ChannelCommand &channel_cmd = get<ChannelCommand>(cmd.command.get());
	const ChannelOutputCommand *output_cmd_ptr = get<ChannelOutputCommand>(&(channel_cmd.channel_command));
	if (!output_cmd_ptr)
		return false;
	const OutputSetCommand* set_cmd_ptr = get<OutputSetCommand>(&(output_cmd_ptr->cmd));
	if (!set_cmd_ptr)
		return false;
	//Check value
	if(fabs(set_cmd_ptr->value - value) > Tolerance)
		return false;
	return true;
}


bool matchChannelRegulatorKeep(optional<double> value, const Command& cmd)
{
	const ChannelCommand &channel_cmd = get<ChannelCommand>(cmd.command.get());
	const ChannelKeepCommand *keep_command_ptr = get<ChannelKeepCommand>(&(channel_cmd.channel_command));
	if(!keep_command_ptr)
		return false;

	if(value) 	//Check value if provided
	{
		double actual_value = *value;
		if(fabs(actual_value - *keep_command_ptr->value) > Tolerance)
			return false;
	}
	else
	{
		//empty command value expected
		if(keep_command_ptr->value)
			return false;
	}
	return true;
}



BOOST_AUTO_TEST_CASE( command_parser_test )
{
	Command cmd;
	BOOST_CHECK( CommandParser::parseCommand( "channel[xyz].input.get", cmd ) );
	BOOST_CHECK( checkParsed(cmd) );
	BOOST_CHECK( matchChannelName("xyz", cmd ) );
	BOOST_CHECK( matchChannelInputGet(cmd) ); 

	BOOST_CHECK( CommandParser::parseCommand( "channel[zzz].output.set(5)", cmd ) );
	BOOST_CHECK( matchChannelName("zzz", cmd ) );
	BOOST_CHECK( matchChannelOutputSet(5, cmd) );

	BOOST_CHECK( CommandParser::parseCommand( "channel[ch0].keep", cmd ) );
	BOOST_CHECK( matchChannelName("ch0", cmd ) );
	BOOST_CHECK( matchChannelRegulatorKeep( optional<double>(), cmd ) );

	BOOST_CHECK( CommandParser::parseCommand( "channel[ch0].keep(12)", cmd ) );
	BOOST_CHECK( matchChannelRegulatorKeep(optional<double>(12), cmd ) );
	
}
